home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
SGI Developer Toolbox 6.1
/
SGI Developer Toolbox 6.1 - Disc 4.iso
/
src
/
haeberli
/
libgutil
/
subpix.c
< prev
next >
Wrap
C/C++ Source or Header
|
1994-08-01
|
8KB
|
374 lines
/*
* Copyright 1991, 1992, 1993, 1994, Silicon Graphics, Inc.
* All Rights Reserved.
*
* This is UNPUBLISHED PROPRIETARY SOURCE CODE of Silicon Graphics, Inc.;
* the contents of this file may not be disclosed to third parties, copied or
* duplicated in any form, in whole or in part, without the prior written
* permission of Silicon Graphics, Inc.
*
* RESTRICTED RIGHTS LEGEND:
* Use, duplication or disclosure by the Government is subject to restrictions
* as set forth in subdivision (c)(1)(ii) of the Rights in Technical Data
* and Computer Software clause at DFARS 252.227-7013, and/or in similar or
* successor clauses in the FAR, DOD or NASA FAR Supplement. Unpublished -
* rights reserved under the Copyright Laws of the United States.
*/
/*
* subpix -
* subpixel positioned trapazoid and line prims.
*
* exports:
trappixel_callback(func)
trapspan_callback(func)
filltri(x0,y0,x1,y1,x2,y2,fatness)
filltrap(x0,y0,w0,x1,y1,w1,fatness)
subpixline(x0,y0,x1,y1,width)
void subpixpoint(fx,fy)
*
* In general the floating point coordinate 0.0,0.0 maps to
* the center of pixel [0,0]. Here are some examples of
* this sampling:
*
* filltrap(-0.5,-0.5,1.0,-0.5,0.5,1.0,0.0) fills pixel[0,0]
* subpixpoint(0.5,0.5) fills pixels [0,0], [0,1], [1,0], [1,1]
* subpixline(-0.5,0.0,0.5,0.0,1.0) fills pixel [0,0]
*
* Paul Haeberli - 1990
*
*/
#include "math.h"
#define EPSILON 0.000001
float flerp();
static Xsubpixline();
static Ysubpixline();
static vline();
static void (*pixfunc)();
static void (*spanfunc)();
static void defspanfunc(xmin, xmax, y)
int xmin, xmax, y;
{
int x;
for(x=xmin; x<=xmax; x++)
(*pixfunc)(x,y);
}
static void pixtospan(int x,int y)
{
(*spanfunc)(x,x,y);
}
trappixel_callback(func)
void (*func)();
{
pixfunc = func;
spanfunc = defspanfunc;
}
trapspan_callback(func)
void (*func)();
{
spanfunc = func;
pixfunc = pixtospan;
}
/*
* filltri -
* point sampling triangle fill.
*
*/
filltri(x0,y0,x1,y1,x2,y2,fatness)
float x0, y0, x1, y1, x2, y2, fatness;
{
int i;
float pos[3][2], temp0, temp1, xmid, ymid, d, p, w;
if(fatness>EPSILON) {
subpixline(x0,y0,x1,y1,fatness);
subpixline(x1,y1,x2,y2,fatness);
subpixline(x2,y2,x0,y0,fatness);
}
pos[0][0] = x0;
pos[0][1] = y0;
pos[1][0] = x1;
pos[1][1] = y1;
pos[2][0] = x2;
pos[2][1] = y2;
if(pos[1][1]<pos[0][1]) {
temp0 = pos[0][0];
temp1 = pos[0][1];
pos[0][0] = pos[1][0];
pos[0][1] = pos[1][1];
pos[1][0] = temp0;
pos[1][1] = temp1;
}
if(pos[2][1]<pos[1][1]) {
temp0 = pos[1][0];
temp1 = pos[1][1];
pos[1][0] = pos[2][0];
pos[1][1] = pos[2][1];
pos[2][0] = temp0;
pos[2][1] = temp1;
}
if(pos[1][1]<pos[0][1]) {
temp0 = pos[0][0];
temp1 = pos[0][1];
pos[0][0] = pos[1][0];
pos[0][1] = pos[1][1];
pos[1][0] = temp0;
pos[1][1] = temp1;
}
d = pos[2][1]-pos[0][1];
if(d<EPSILON)
p = 0.0;
else
p = (pos[1][1]-pos[0][1])/d;
xmid = flerp(pos[0][0],pos[2][0],p);
ymid = pos[1][1];
if(xmid<pos[1][0]) {
w = pos[1][0]-xmid;
filltrap(pos[0][0],pos[0][1],0.0,xmid,ymid,w,0.0);
filltrap(xmid,ymid,w,pos[2][0],pos[2][1],0.0,0.0);
} else {
w = xmid - pos[1][0];
filltrap(pos[0][0],pos[0][1],0.0,pos[1][0],pos[1][1],w,0.0);
filltrap(pos[1][0],pos[1][1],w,pos[2][0],pos[2][1],0.0,0.0);
}
}
/*
* filltrap -
* point sampling trapazoid fill. Remember: y0 is assumed to
* be less than y1.
*
*/
filltrap(x0,y0,w0,x1,y1,w1,fatness)
float x0, y0, w0, x1, y1, w1, fatness;
{
float ymin, deltay, p, mp;
float rx0, rx1, xmin, xmax, yline;
int y, iyline, ixmin, ixmax;
/* surround it with lines if thick */
if(fatness>EPSILON) {
subpixline(x0,y0,x0+w0,y0,fatness);
subpixline(x0+w0,y0,x1+w1,y1,fatness);
subpixline(x1+w1,y1,x1,y1,fatness);
subpixline(x1,y1,x0,y0,fatness);
}
x0 += 0.5;
y0 += 0.5;
x1 += 0.5;
y1 += 0.5;
/* find the height of the trap */
deltay = y1-y0;
if(deltay<EPSILON)
return 0;
/* get the right hand x coords */
rx0 = x0+w0-0.5;
rx1 = x1+w1-0.5;
x0 = x0+0.5;
x1 = x1+0.5;
/* get the first y scanline pos */
ymin = floor(y0)+0.5;
/* if below bottom, increment */
if(ymin<y0)
y = 1;
else
y = 0;
yline = ymin+y;
iyline = floor(yline);
while(yline<y1) {
p = (yline-y0)/deltay; /* calculate parameter */
mp = 1.0-p;
xmin = mp*x0+p*x1;
xmax = mp*rx0+p*rx1;
ixmin = floor(xmin);
ixmax = floor(xmax);
if(ixmax>=ixmin)
(*spanfunc)(ixmin,ixmax,iyline);
y++;
iyline++;
yline = ymin+y;
}
}
/*
* subpixel positioned line
*
*/
subpixline(x0,y0,x1,y1,width)
float x0, y0, x1, y1, width;
{
float dx, dy;
x0 += 0.5;
y0 += 0.5;
x1 += 0.5;
y1 += 0.5;
dx = x1-x0;
if(dx<0.0)
dx = -dx;
dy = y1-y0;
if(dy<0.0)
dy = -dy;
if(dy>dx)
Ysubpixline(x0,y0,x1,y1,width);
else
Xsubpixline(x0,y0,x1,y1,width);
}
static Xsubpixline(x0,y0,x1,y1,width)
float x0, y0, x1, y1, width;
{
float xmin, deltax, deltay, p, mp;
float ymin, xline;
int x, ixline, iymin;
float temp;
float w0, ry0, ry1, ymax;
int iymax;
/* swap endpoints if they're in the wrong order */
if(x1<x0) {
temp = x1;
x1 = x0;
x0 = temp;
temp = y1;
y1 = y0;
y0 = temp;
}
/* find the width of the line */
deltax = x1-x0;
deltay = y1-y0;
if(deltax<EPSILON)
return 0;
/* apply the width */
#ifdef WIDTH_CORRECT
width = width*sqrt(deltax*deltax+deltay*deltay)/deltax;
#endif
width = (width-1.0)/2.0;
ry0 = y0+width;
ry1 = y1+width;
y0 -= width;
y1 -= width;
/* get the first y scanline pos */
xmin = floor(x0)+0.5;
/* if to left of left , increment */
if(xmin<x0)
x = 1;
else
x = 0;
xline = xmin+x;
ixline = floor(xline);
while(xline<x1) {
p = (xline-x0)/deltax; /* calculate parameter */
mp = 1.0-p;
ymin = mp*y0+p*y1;
ymax = mp*ry0+p*ry1;
iymin = floor(ymin);
iymax = floor(ymax);
if(iymax>=iymin)
vline(iymin,iymax,ixline);
x++;
ixline++;
xline = xmin+x;
}
}
static Ysubpixline(x0,y0,x1,y1,width)
float x0, y0, x1, y1, width;
{
float ymin, deltax, deltay, p, mp;
float xmin, yline;
int y, iyline, ixmin;
float temp;
float w0, rx0, rx1, xmax;
int ixmax;
/* swap endpoints if they're in the wrong order */
if(y1<y0) {
temp = y1;
y1 = y0;
y0 = temp;
temp = x1;
x1 = x0;
x0 = temp;
}
/* find the height of the line */
deltax = x1-x0;
deltay = y1-y0;
if(deltay<EPSILON)
return 0;
/* apply the width */
#ifdef WIDTH_CORRECT
width = width*sqrt(deltax*deltax+deltay*deltay)/deltay;
#endif
width = (width-1.0)/2.0;
rx0 = x0+width;
rx1 = x1+width;
x0 -= width;
x1 -= width;
/* get the first y scanline pos */
ymin = floor(y0)+0.5;
/* if below bottom, increment */
if(ymin<y0)
y = 1;
else
y = 0;
yline = ymin+y;
iyline = floor(yline);
while(yline<y1) {
p = (yline-y0)/deltay; /* calculate parameter */
mp = 1.0-p;
xmin = mp*x0+p*x1;
xmax = mp*rx0+p*rx1;
ixmin = floor(xmin);
ixmax = floor(xmax);
if(ixmax>=ixmin)
(*spanfunc)(ixmin,ixmax,iyline);
y++;
iyline++;
yline = ymin+y;
}
}
void subpixpoint(fx,fy)
float fx, fy;
{
int ix, iy;
ix = (int) floor(fx);
iy = (int) floor(fy);
(*spanfunc)(ix,ix+1,iy);
(*spanfunc)(ix,ix+1,iy+1);
}
static vline(ymin,ymax,x)
int ymin, ymax, x;
{
int y;
for(y=ymin; y<=ymax; y++)
(*pixfunc)(x,y);
}